<?php
namespace CC\Service;
use Bisna\Service\Service as BisnaService;

class HelpdeskService extends BisnaService
{

    /**
     * Create a new ticket
     */
    public function newTicket()
    {
    }

    /**
     * Assign a ticket to a user
     */
    public function esculateTicket($ticketId, $userId, $message)
    {
        $em = $this->getEntityManager();
        /**
         * @var CC\Entity\Ticket
         */
        $ticket = $em->getRepository('CC\Entity\Ticket')->findOneById($ticketId);
        $user = $em->getRepository('CC\Entity\User')->findOneById($userId);
        $origUser = $ticket->getUser();
        
        $esculateComment = "<p>
        						<strong>Owner: </strong>{$origUser->getFirstname()} {$origUser->getSurname()}<br />
        						<strong>Esculated ticket to: </strong>{$user->getFirstname()} {$user->getSurname()}
        					</p></br />";
        $esculateComment .= $message;
        
        $ticket->setUser($user);
        $ticket->setFolder(null);
        $em->persist($ticket);
        $em->flush();
        
        $this->_createComment($user->getId(), $ticketId, $esculateComment, 'esculation');
        
        // Parse ticket rules and actions
        $parser = new \CC_Helpdesk_RuleParser(new \CC_Helpdesk_ActionParser($this->getEntityManager()), $ticket, $user);
        $parser->parse();
        
        return true;
    }
    
    /**
     * 
     */
    public function assignToFolder($ticketId, $folderId)
    {
        $em = $this->getEntityManager();
        
        $ticket = $em->getRepository('CC\Entity\Ticket')->findOneById($ticketId);
        $folder = $em->getReference('CC\Entity\Folder', $folderId);
        $ticket->setFolder($folder);
        $em->persist($ticket);
        $em->flush();
    }
    
    /**
     * Add a new user comment to the ticket
     */
    public function addUserComment($commentMessage, $userId, $ticketId)
    {
        return $this->_createComment($userId, $ticketId, $commentMessage, 'user');
    }

    /**
     * View a ticket conversation
     * 
     * @param integer $ticketId Ticket ID
     * @param integer $userId User ID
     */
    public function getTicket($ticketId, $userId)
    {
        $em = $this->getEntityManager();
        $ticketArray = array();
        
        // Check if the ticket belongs to the user
        $dql = 'SELECT count(t.id) 
	    		FROM CC\Entity\Ticket t
	    		WHERE t.user = ?1
	    		  AND t.id = ?2';
        $ticketExists = $em->createQuery($dql)
            ->setParameter(1, $userId)
            ->setParameter(2, $ticketId)
            ->getResult();
            
        if($ticketExists)
        {
            $dql = 'SELECT t, tc
            		FROM CC\Entity\Ticket t
            		LEFT JOIN t.comments tc
            		WHERE t.id = ?1
            		ORDER BY tc.created DESC';
            $ticket = $em->createQuery($dql)
                ->setParameter(1, $ticketId)
                ->getResult();
                
            // Ensure ticket result is valid
            if(is_array($ticket) && count($ticket))
            {
                // For some unknown reason the query will always return an array
                $ticket = $ticket[0];
                $ticketComments = $ticket->getComments();
                $ticketArray = array(
                    'from' => $ticket->getFrom(), 
                    'subject' => $ticket->getSubject(), 
                    'source' => $ticket->getSource(), 
                    'created' => $ticket->getCreated()->getTimestamp(), 
                    'attachment' => $ticket->hasAttachment()
                );
                
                foreach($ticketComments as $comment)
                {
                    $tmpComment = array(
                        'comment' => $comment->getComment(), 
                        'created' => $comment->getCreated()->getTimestamp(), 
                        'source' => $comment->getSource()
                    );
                    
                    $ticketArray['comments'][] = $tmpComment;
                }
                return $ticketArray;
            }
        }
        return false;
    }

    /**
     * Retrieves a list of the users tickets 
     */
    public function getUserTickets($userId, $folderId)
    {
        $em = $this->getEntityManager();
        $ticketArray = array();
        $params['1'] = $userId;
        if($folderId == 0)
        {
            $dql = 'SELECT t FROM CC\Entity\Ticket t
            		WHERE t.user = ?1
            		  AND t.folder IS NULL
            		ORDER BY t.created DESC';
        }
        else
        {
            $dql = 'SELECT t FROM CC\Entity\Ticket t
            		WHERE t.user = ?1
            		  AND t.folder = ?2
            		ORDER BY t.created DESC';
            $params['2'] = $folderId;
        }
        
        $tickets = $em->createQuery($dql)
            ->setParameters($params)
            ->getResult();
            
        foreach($tickets as $ticket)
        {
            $ticketDate = $ticket->getCreated();
            $tmp = array(
                'id' => $ticket->getId(), 'from' => $ticket->getFrom(), 
                'subject' => $ticket->getSubject(), 
                'date' => date('d F Y', $ticket->getCreated()->getTimestamp()), 
                'attachment' => $ticket->hasAttachment()
            );
            
            $ticketArray[] = $tmp;
        }
        return $ticketArray;
    }

    /**
     * Retrieves a list of the providers tickets
     */
    public function getProviderTickets()
    {
    }

    /**
     * Retrieve a list of the users folders
     * 
     * @param integer $userId User ID
     * @return array Recursive array containing the folder id and name
     */
    public function getUserFolders($userId)
    {
        return $this->_generateFolderList($userId);
    }

    /**
     * Create a new folder for the ticket system
     * 
     * @param integer $userId User to create folder for
     * @param integer $parentFolderId Parent folder
     * @param string $folderName Folder name
     * @return boolean Returns true of success
     */
    public function createFolder($userId, $parentFolderId, $folderName)
    {
        $em = $this->getEntityManager();
        $userEntityReference = $em->getReference('CC\Entity\User', $userId);
        
        if($userEntityReference !== null)
        {
            $folder = new \CC\Entity\Folder();
            $folder->setName($folderName);
            $folder->setUser($userEntityReference);
            
            if($parentFolderId != 0)
            {
                $parentEntityReference = $em->getReference('CC\Entity\Folder', 
                $parentFolderId);
                $folder->setParent($parentEntityReference);
            }
            
            try
            {
                $em->persist($folder);
                $em->flush();
                return true;
            }
            catch(\Exception $e)
            {
            }
        }
        return false;
    }

    /**
     * Delete the folder for the specified user
     * If the folder contains any messages, they will be
     * moved to the inbox folder
     * 
     * @param integer $userId User to delete folder for
     * @param integer $folderId Folder Id
     * @return boolean Returns true of success
     */
    public function deleteFolder($userId, $folderId)
    {
        $em = $this->getEntityManager();
        
        // Check if the folder belongs to the user
        $dql = 'SELECT count(f.id) 
	    		FROM CC\Entity\Folder f
	    		WHERE f.id = ?1
	    		  AND f.user = ?2';
        $exists = $em->createQuery($dql)
            ->setParameter(1, $userId)
            ->setParameter(2, $folderId)
            ->getResult();
            
        if($exists)
        {
            try
            {
                // If the folder contains tickets, then move them to the
                // Inbox before deleting the folder.
                // @TODO: Recursive delete... :(
                $hasTickets = false;
                $dql = "SELECT t
                		FROM CC\Entity\Ticket t
                		WHERE t.folder = ?1";
                $folderTickets = $em->createQuery($dql)
                    ->setParameter(1, $folderId)
                    ->getResult();
                    
                foreach($folderTickets as $ticket)
                {
                    $ticket->setFolder(null);
                    $em->persist($ticket);
                    $hasTickets = true;
                }
                
                // Batch update
                if($hasTickets)
                    $em->flush();
                    
                // Remove the folder
                $folderEntity = $em->getRepository('CC\Entity\Folder')->findOneById($folderId);
                $em->remove($folderEntity);
                $em->flush();
                
                return true;
            }
            catch(\Exception $e)
            {
            }
        }
        
        return false;
    }

    /**
     * Retrieves a list of tickets for a specified folder.
     */
    protected function _getTickets()
    {
    }

    /**
     * Generates an array containing the folder id and name for the 
     * user id passed.
     * 
     * @TODO: Enable listing of provider folders
     * 
     * @param integer $userId User ID
     * @param object $folders Used for recursion
     * @return array Recursive array containing the folder id and name
     */
    protected function _generateFolderList($userId, $folders = null)
    {
        $em = $this->getEntityManager();
        
        // This is run on the first execution only as there is no parent folder
        if($folders === null)
        {
            $dql = 'SELECT PARTIAL f.{id, name} 
            		FROM CC\Entity\Folder f 
            		WHERE f.user = ?1 
            		  AND f.parent IS NULL 
            		ORDER BY f.name ASC';
            $folders = $em->createQuery($dql)
                          ->setParameter(1, $userId)
                          ->getResult();
        }
        
        // Voodoo recursion code
        $folderArray = array();
        foreach($folders as $folder)
        {
            $tmpChildren = null;
            $dql = 'SELECT PARTIAL f.{id, name} 
            		FROM CC\Entity\Folder f 
            		WHERE f.user = ?1 
            		  AND f.parent = ?2 
            		ORDER BY f.name ASC';
            $children = $em->createQuery($dql)
                           ->setParameter(1, $userId)
                           ->setParameter(2, $folder->getId())
                           ->getResult();
            if(count($children))
                $tmpChildren = $this->_generateFolderList($userId, $children);
                
            $tmp = array(
                'id' => $folder->getId(), 'name' => $folder->getName()
            );
            
            // Check if there are tickets in the folder
            $dql = 'SELECT COUNT(t.id)
            		FROM CC\Entity\Ticket t
            		WHERE t.folder = ?1
            		  AND t.user = ?2';
            $folderTicketCount = $em->createQuery($dql)
                                    ->setParameter(1, $folder->getId())
                                    ->setParameter(2, $userId)
                                    ->getResult();
            
            $tmp['ticketCount'] = $folderTicketCount[0][1];
            
            if(count($tmpChildren))
            {
                $tmp['children'] = $tmpChildren;
            }
            
            $folderArray[] = $tmp;
        }
        return $folderArray;
    }
    
    public function findUser($query, $userId)
    {
        $em = $this->getEntityManager();
        $user = $em->getRepository('CC\Entity\User')->findOneById($userId);
        
        $users = array();
        $providerId = $user->getProvider()->getId();
        
        $dql = 'SELECT u 
        		FROM CC\Entity\User u
        		WHERE (u.firstname LIKE ?1 OR u.surname LIKE ?1 OR u.email LIKE ?1)
        		  AND u.provider = ?2';
        
        $userEntities = $this->getEntityManager()->createQuery($dql)
                                                 ->setParameter(1, '%'.$query.'%')
                                                 ->setParameter(2, $providerId)
                                                 ->getResult();
        
        foreach($userEntities as $user)
        {
            $tmp = array(
                'id'    => $user->getId(),
                'name'  => $user->getFirstname().' '.$user->getSurname(),
                'email' => $user->getEmail()
            );
            
            $users[] = $tmp;
        }
        
        return $users;
    }
    
    public function getUserIdFromEmail($email, $userId)
    {
        $em = $this->getEntityManager();
        $user = $em->getRepository('CC\Entity\User')->findOneById($userId);
        
        $providerId = $user->getProvider()->getId();
        
        $dql = 'SELECT u
        		FROM CC\Entity\User u
        		WHERE u.email = ?1
        		  AND u.provider = ?2';
        $userEntities = $em->createQuery($dql)
                           ->setParameter(1, $email)
                           ->setParameter(2, $providerId)
                           ->getResult();
         
         if(count($userEntities))
         {
             $user = $userEntities[0];
             return $user->getId();
         }
         
         return null;
    }
    
    public static function getTicketRefFromId($ticketId)
    {
        $helpdeskConfig = \Zend_Registry::get('config')->helpdesk;
        
        $idPadding = $helpdeskConfig->ticket->idPadding;
        $refPrefix = $helpdeskConfig->ticket->referencePrefix;
        $ticketRef = "#".$refPrefix."-".str_pad($ticketId, $idPadding, 0, STR_PAD_LEFT);
        
        return $ticketRef;
    }
    
    protected function _createComment($userId, $ticketId, $message, $source)
    {
        try 
        {
            $em = $this->getEntityManager();
            $userEntity = $em->getReference('CC\Entity\User', $userId);
            $ticketEntity = $em->getRepository('CC\Entity\Ticket')->findOneById($ticketId);
            
            $comment = new \CC\Entity\TicketComment();
            $comment->setComment($message);
            $comment->setUser($userEntity);
            $comment->setSource($source);
            
            $ticketEntity->addComment($comment);
            
            $em->persist($comment);
            $em->persist($ticketEntity);
            $em->flush();
            
            return true;
        }
        catch(Exception $e)
        { }
        
        return false;
    }
}
